
/* drivers/video/sc8825/lcd_ili9881d_mipi.c
 *
 * Support for ili9881d mipi LCD device
 *
 * Copyright (C) 2010 Spreadtrum
 *
 * This software is licensed under the terms of the GNU General Public
 * License version 2, as published by the Free Software Foundation, and
 * may be copied, distributed, and modified under those terms.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 */

#include "sprd_panel.h"
#include "sprd_dsi.h"
#include "dsi/mipi_dsi_api.h"
#include "sprd_dphy.h"

#define  LCD_DEBUG
#ifdef LCD_DEBUG
#define LCD_PRINT printk
#else
#define LCD_PRINT(...)
#endif

#define MAX_DATA   56



static uint8_t init_data[] = {
	0x39, 0x00, 0x00,4,0xFF,0x98,0x81,0x05,
	0x23, 0x00, 0x00,2,0xB2,0x70,
	0x23, 0x00, 0x00,2,0x03,0x00,
	0x23, 0x00, 0x00,2,0x04,0x2C,

	0x23, 0x00, 0x00,2,0x4C,0x11,

	0x23, 0x00, 0x00,2,0x1A,0x50,
	0x23, 0x00, 0x00,2,0x38,0xA0,
	0x23, 0x00, 0x00,2,0x4D,0x22,
	0x23, 0x00, 0x00,2,0x54,0x28,
	0x23, 0x00, 0x00,2,0x55,0x25,

	0x23, 0x00, 0x00,2,0x1B,0x09,
	0x23, 0x00, 0x00,2,0x26,0x0E,

	0x23, 0x00, 0x00,2,0x78,0x01,
	0x23, 0x00, 0x00,2,0xA9,0xC0,
	0x23, 0x00, 0x00,2,0xB1,0x70,
	0x23, 0x00, 0x00,2,0x1E,0x11,

	0x39, 0x00, 0x00,4,0xFF,0x98,0x81,0x02,
	0x23, 0x00, 0x00,2,0x01,0x50,
	0x23, 0x00, 0x00,2,0x15,0x10,
	0x23, 0x00, 0x00,2,0x42,0x01,
	0x23, 0x00, 0x00,2,0x44,0x01,

	0x39, 0x00, 0x00,21,0x57,0x00,0x1B,0x2B,0x13,0x16,0x29,0x1E,0x1F,0x90,0x1E,0x2B,0x79,0x18,0x12,0x41,0x1E,0x26,0x4E,0x5D,0x2C,
	0x39, 0x00, 0x00,21,0x6B,0x00,0x1B,0x2B,0x13,0x16,0x29,0x1E,0x1F,0x90,0x1E,0x2B,0x79,0x18,0x12,0x41,0x1E,0x26,0x4E,0x5D,0x2C,

	0x39, 0x00, 0x00,4,0xFF,0x98,0x81,0x01,
	0x23, 0x00, 0x00,2,0x01,0x00,
	0x23, 0x00, 0x00,2,0x02,0x00,
	0x23, 0x00, 0x00,2,0x03,0x56,
	0x23, 0x00, 0x00,2,0x04,0x13,
	0x23, 0x00, 0x00,2,0x05,0x13,
	0x23, 0x00, 0x00,2,0x06,0x0A,
	0x23, 0x00, 0x00,2,0x07,0x05,
	0x23, 0x00, 0x00,2,0x08,0x05,
	0x23, 0x00, 0x00,2,0x09,0x1D,
	0x23, 0x00, 0x00,2,0x0A,0x01,
	0x23, 0x00, 0x00,2,0x0B,0x00,
	0x23, 0x00, 0x00,2,0x0C,0x3F,
	0x23, 0x00, 0x00,2,0x0D,0x29,
	0x23, 0x00, 0x00,2,0x0E,0x29,
	0x23, 0x00, 0x00,2,0x0F,0x1D,
	0x23, 0x00, 0x00,2,0x10,0x1D,
	0x23, 0x00, 0x00,2,0x11,0x00,
	0x23, 0x00, 0x00,2,0x12,0x00,
	0x23, 0x00, 0x00,2,0x13,0x08,
	0x23, 0x00, 0x00,2,0x14,0x08,
	0x23, 0x00, 0x00,2,0x15,0x00,
	0x23, 0x00, 0x00,2,0x16,0x00,
	0x23, 0x00, 0x00,2,0x17,0x00,
	0x23, 0x00, 0x00,2,0x18,0x00,
	0x23, 0x00, 0x00,2,0x19,0x00,
	0x23, 0x00, 0x00,2,0x1A,0x00,
	0x23, 0x00, 0x00,2,0x1B,0x00,
	0x23, 0x00, 0x00,2,0x1C,0x00,
	0x23, 0x00, 0x00,2,0x1D,0x00,
	0x23, 0x00, 0x00,2,0x1E,0x40,
	0x23, 0x00, 0x00,2,0x1F,0x88,
	0x23, 0x00, 0x00,2,0x20,0x08,
	0x23, 0x00, 0x00,2,0x21,0x01,
	0x23, 0x00, 0x00,2,0x22,0x00,
	0x23, 0x00, 0x00,2,0x23,0x00,
	0x23, 0x00, 0x00,2,0x24,0x00,
	0x23, 0x00, 0x00,2,0x25,0x00,
	0x23, 0x00, 0x00,2,0x26,0x00,
	0x23, 0x00, 0x00,2,0x27,0x00,
	0x23, 0x00, 0x00,2,0x28,0x33,
	0x23, 0x00, 0x00,2,0x29,0x03,
	0x23, 0x00, 0x00,2,0x2A,0x00,
	0x23, 0x00, 0x00,2,0x2B,0x00,
	0x23, 0x00, 0x00,2,0x2C,0x00,
    0x23, 0x00, 0x00,2,0x2D,0x00,
    0x23, 0x00, 0x00,2,0x2E,0x00,
    0x23, 0x00, 0x00,2,0x2F,0x00,
    0x23, 0x00, 0x00,2,0x30,0x00,
    0x23, 0x00, 0x00,2,0x31,0x00,
    0x23, 0x00, 0x00,2,0x32,0x00,
    0x23, 0x00, 0x00,2,0x33,0x00,
    0x23, 0x00, 0x00,2,0x34,0x00,
    0x23, 0x00, 0x00,2,0x35,0x00,
    0x23, 0x00, 0x00,2,0x36,0x00,
    0x23, 0x00, 0x00,2,0x37,0x00,
    0x23, 0x00, 0x00,2,0x38,0x00,
    0x23, 0x00, 0x00,2,0x39,0x0F,
    0x23, 0x00, 0x00,2,0x3A,0x2A,
    0x23, 0x00, 0x00,2,0x3B,0x00,
    0x23, 0x00, 0x00,2,0x3C,0x00,
    0x23, 0x00, 0x00,2,0x3D,0x00,
    0x23, 0x00, 0x00,2,0x3E,0x00,
    0x23, 0x00, 0x00,2,0x3F,0x00,
    0x23, 0x00, 0x00,2,0x40,0x00,
    0x23, 0x00, 0x00,2,0x41,0xE0,
    0x23, 0x00, 0x00,2,0x42,0x40,
    0x23, 0x00, 0x00,2,0x43,0x0F,
    0x23, 0x00, 0x00,2,0x44,0x11,
    0x23, 0x00, 0x00,2,0x45,0xA8,
    0x23, 0x00, 0x00,2,0x46,0x00,
    0x23, 0x00, 0x00,2,0x47,0x08,
    0x23, 0x00, 0x00,2,0x48,0x00,
    0x23, 0x00, 0x00,2,0x49,0x01,
    0x23, 0x00, 0x00,2,0x4A,0x00,
    0x23, 0x00, 0x00,2,0x4B,0x00,


    0x23, 0x00, 0x00,2,0x4C,0xB2,
    0x23, 0x00, 0x00,2,0x4D,0x22,
    0x23, 0x00, 0x00,2,0x4E,0x01,
    0x23, 0x00, 0x00,2,0x4F,0xF7,
    0x23, 0x00, 0x00,2,0x50,0x29,
    0x23, 0x00, 0x00,2,0x51,0x72,
    0x23, 0x00, 0x00,2,0x52,0x25,
    0x23, 0x00, 0x00,2,0x53,0xB2,
    0x23, 0x00, 0x00,2,0x54,0x22,
    0x23, 0x00, 0x00,2,0x55,0x22,
    0x23, 0x00, 0x00,2,0x56,0x22,

    0x23, 0x00, 0x00,2,0x57,0xA2,
    0x23, 0x00, 0x00,2,0x58,0x22,
    0x23, 0x00, 0x00,2,0x59,0x01,
    0x23, 0x00, 0x00,2,0x5A,0xE6,
    0x23, 0x00, 0x00,2,0x5B,0x28,
    0x23, 0x00, 0x00,2,0x5C,0x62,
    0x23, 0x00, 0x00,2,0x5D,0x24,
    0x23, 0x00, 0x00,2,0x5E,0xA2,
    0x23, 0x00, 0x00,2,0x5F,0x22,
    0x23, 0x00, 0x00,2,0x60,0x22,
    0x23, 0x00, 0x00,2,0x61,0x22,

    0x23, 0x00, 0x00,2,0x62,0xEE,

    0x23, 0x00, 0x00,2,0x63,0x02,
    0x23, 0x00, 0x00,2,0x64,0x0B,
    0x23, 0x00, 0x00,2,0x65,0x02,
    0x23, 0x00, 0x00,2,0x66,0x02,
    0x23, 0x00, 0x00,2,0x67,0x01,
    0x23, 0x00, 0x00,2,0x68,0x00,
    0x23, 0x00, 0x00,2,0x69,0x0F,
    0x23, 0x00, 0x00,2,0x6A,0x07,
    0x23, 0x00, 0x00,2,0x6B,0x55,
    0x23, 0x00, 0x00,2,0x6C,0x02,
    0x23, 0x00, 0x00,2,0x6D,0x02,
    0x23, 0x00, 0x00,2,0x6E,0x5B,
    0x23, 0x00, 0x00,2,0x6F,0x59,
    0x23, 0x00, 0x00,2,0x70,0x02,
    0x23, 0x00, 0x00,2,0x71,0x02,
    0x23, 0x00, 0x00,2,0x72,0x57,
    0x23, 0x00, 0x00,2,0x73,0x02,
    0x23, 0x00, 0x00,2,0x74,0x02,
    0x23, 0x00, 0x00,2,0x75,0x02,
    0x23, 0x00, 0x00,2,0x76,0x02,
    0x23, 0x00, 0x00,2,0x77,0x02,
    0x23, 0x00, 0x00,2,0x78,0x02,

    0x23, 0x00, 0x00,2,0x79,0x02,
    0x23, 0x00, 0x00,2,0x7A,0x0A,
    0x23, 0x00, 0x00,2,0x7B,0x02,
    0x23, 0x00, 0x00,2,0x7C,0x02,
    0x23, 0x00, 0x00,2,0x7D,0x01,
    0x23, 0x00, 0x00,2,0x7E,0x00,
    0x23, 0x00, 0x00,2,0x7F,0x0E,
    0x23, 0x00, 0x00,2,0x80,0x06,
    0x23, 0x00, 0x00,2,0x81,0x54,
    0x23, 0x00, 0x00,2,0x82,0x02,
    0x23, 0x00, 0x00,2,0x83,0x02,
    0x23, 0x00, 0x00,2,0x84,0x5A,
    0x23, 0x00, 0x00,2,0x85,0x58,
    0x23, 0x00, 0x00,2,0x86,0x02,
    0x23, 0x00, 0x00,2,0x87,0x02,
    0x23, 0x00, 0x00,2,0x88,0x56,
    0x23, 0x00, 0x00,2,0x89,0x02,
    0x23, 0x00, 0x00,2,0x8A,0x02,
    0x23, 0x00, 0x00,2,0x8B,0x02,
    0x23, 0x00, 0x00,2,0x8C,0x02,
    0x23, 0x00, 0x00,2,0x8D,0x02,
    0x23, 0x00, 0x00,2,0x8E,0x02,

    0x23, 0x00, 0x00,2,0x8F,0x44,
    0x23, 0x00, 0x00,2,0x90,0x44,

    0x39, 0x00, 0x00,4,0xFF,0x98,0x81,0x06,
    0x23, 0x00, 0x00,2,0x01,0x03,
    0x23, 0x00, 0x00,2,0x2B,0x0A,
    0x23, 0x00, 0x00,2,0x04,0x70,

    0x23, 0x00, 0x00,2,0xC0,0xCF,
    0x23, 0x00, 0x00,2,0xC1,0x2A,

    0x39, 0x00, 0x00,4,0xFF,0x98,0x81,0x00,
    0x23, 0x78, 0x00,2,0x11,0x00,
    0x23, 0x0a, 0x00,2,0x29,0x00,

    0x23, 0x00, 0x00,2,0x35,0x00,
    0x23, 0x00, 0x00,2,0x36,0x00,
    CMD_END
};

static int mipi_dsi_send_cmds(struct sprd_dsi *dsi, void *data)
{
	uint16_t len;
	struct dsi_cmd_desc *cmds = data;

	if ((cmds == NULL) || (dsi == NULL))
		return -1;

	for (; cmds->data_type != CMD_END;) {
		len = (cmds->wc_h << 8) | cmds->wc_l;
		mipi_dsi_gen_write(dsi, cmds->payload, len);
		if (cmds->wait)
			msleep(cmds->wait);
		cmds = (struct dsi_cmd_desc *)(cmds->payload + len);
	}
	return 0;
}

static int32_t ili9881p_mipi_init(struct panel_spec *self)
{
	struct sprd_dsi *dsi = &dsi_device;
	struct sprd_dphy *dphy = &dphy_device;
        LCD_PRINT("lcd_ili9881p_mipi init! \n");

	mipi_dsi_lp_cmd_enable(dsi, true);
	mipi_dsi_send_cmds(dsi, init_data);
	mipi_dsi_set_work_mode(dsi, SPRD_MIPI_MODE_VIDEO);
	mipi_dsi_state_reset(dsi);
	mipi_dphy_hs_clk_en(dphy, true);

	return 0;
}


static uint32_t ili9881p_readid(struct panel_spec *self)
{
#if 0
  	struct sprd_dsi *dsi = &dsi_device;
	//uint8_t cmd[] = {0xFF, 0x98, 0x81, 0x06};
	uint8_t read_buf[4] = {0};

        LCD_PRINT("lcd_ili9881p_mipi read id!(KBLK-AD55442-V10)\n");

	//return 0x9881;
       mipi_dsi_lp_cmd_enable(dsi, true);
	//mipi_dsi_gen_write(dsi, cmd, ARRAY_SIZE(cmd));
	mipi_dsi_set_max_return_size(dsi, 3);
	mipi_dsi_dcs_read(dsi, 0x04, &read_buf[0], 3);
//	mipi_dsi_dcs_read(dsi, 0x1, &read_buf[1], 1);
//	mipi_dsi_dcs_read(dsi, 0x2, &read_buf[2], 1);	
       LCD_PRINT("lcd_ili9881p_mipi read id 0x00 value is 0x%x, 0x%x, 0x%x!\n", read_buf[0], read_buf[1], read_buf[2]);

       if((0x98 == read_buf[0])&&(0x81 == read_buf[1]) && (0x04 == read_buf[2])){
                      LCD_PRINT("lcd_ili9881p_mipi read id success!\n");
                       return 0x9881106f;
        }

        return 0;
#else
	struct sprd_dsi *dsi = &dsi_device;
	uint8_t cmd[] = {0xFF, 0x98, 0x81, 0x06};
	uint8_t read_buf[4] = {0};

	mipi_dsi_lp_cmd_enable(dsi, true);
	mipi_dsi_gen_write(dsi, cmd, ARRAY_SIZE(cmd));
	mdelay(5);
	mipi_dsi_set_max_return_size(dsi, 1);
	mipi_dsi_dcs_read(dsi, 0xf0, &read_buf[0], 1);
	mipi_dsi_dcs_read(dsi, 0xf1, &read_buf[1], 1);
	mipi_dsi_dcs_read(dsi, 0xf2, &read_buf[2], 1);

       LCD_PRINT("lcd_ili9881p_mipi read id 0x00 value is 0x%x, 0x%x, 0x%x!\n", read_buf[0], read_buf[1], read_buf[2]);

	if ((read_buf[0] == 0x98) && (read_buf[1] == 0x81)&& (read_buf[2] == 0x04)) {
		LCD_PRINT("ili9881p read id success!\n");
		return 0;
	}

	LCD_PRINT("ili9881p read id failed!\n");
	return -1;	
#endif	
}

static int32_t ili9881p_power(int on)
{
	if (on) {
        LCD_PRINT("lcd_ili9881p_mipi on! \n");
		
		sprd_gpio_request(NULL, CONFIG_LCM_GPIO_RSTN);
		sprd_gpio_direction_output(NULL, CONFIG_LCM_GPIO_RSTN, 1);
		mdelay(5);
		sprd_gpio_direction_output(NULL, CONFIG_LCM_GPIO_RSTN, 0);
		mdelay(10);
		sprd_gpio_direction_output(NULL, CONFIG_LCM_GPIO_RSTN, 1);
		mdelay(120);
	} else {
	        LCD_PRINT("lcd_ili9881p_mipi off! \n");
		sprd_gpio_direction_output(NULL, CONFIG_LCM_GPIO_RSTN, 0);
		mdelay(5);
	}

	return 0;
}

static struct panel_ops lcd_ili9881p_mipi_operations = {
	.init = ili9881p_mipi_init,
	.read_id = ili9881p_readid,
	.power = ili9881p_power,
};
#if 0
static struct timing_rgb lcd_ili9881d_mipi_timing = {
	.hfp = 30,	/* unit: pixel */
	.hbp = 30,
	.hsync = 20,
	.vfp = 10, /*unit: line*/
	.vbp = 14,
	.vsync = 12,
};

static struct info_mipi lcd_ili9881d_mipi_info = {
	.work_mode  = SPRDFB_MIPI_MODE_VIDEO,
	.video_bus_width = 24, /*18,16*/
	.lan_number = 4,
	.phy_feq = 542*1000,
	.h_sync_pol = SPRDFB_POLARITY_POS,
	.v_sync_pol = SPRDFB_POLARITY_POS,
	.de_pol = SPRDFB_POLARITY_POS,
	.te_pol = SPRDFB_POLARITY_POS,
	.color_mode_pol = SPRDFB_POLARITY_NEG,
	.shut_down_pol = SPRDFB_POLARITY_NEG,
	.timing = &lcd_ili9881d_mipi_timing,
	.ops = NULL,
};

struct panel_spec lcd_ili9881p_kblk_ad55442_v10_mipi_spec = {
	.width = 720,
	.height = 1440,
	.fps = 60,
	.type = LCD_MODE_DSI,
	.direction = LCD_DIRECT_NORMAL,
	.is_need_reset = 1,
	.info = {
		.mipi = &lcd_ili9881d_mipi_info
	},
	.ops = &lcd_ili9881d_mipi_operations,
};
#endif
static struct panel_info lcd_ili9881p_kblk_ad55442_v10_info = {
	/* common parameters */
	.lcd_name = "lcd_ili9881p_kblk_ad55442_v10_mipi",
	.type = SPRD_PANEL_TYPE_MIPI,
	.bpp = 24,
//	.fps = 3,
	.width = 720,
	.height = 1440,

	/* DPI specific parameters */
	.pixel_clk = 76800000,
	.rgb_timing = {
		.hfp = 30,
		.hbp = 30,
		.hsync = 20,
		.vfp = 10,
		.vbp = 14,
		.vsync = 12,
	},

	/* MIPI DSI specific parameters */
	.phy_freq = 542000,
	.lane_num = 4,
	.work_mode = SPRD_MIPI_MODE_VIDEO,
	.burst_mode = PANEL_VIDEO_BURST_MODE,
	.nc_clk_en = false,
};

struct panel_driver lcd_ili9881p_kblk_ad55442_v10_driver = {
	.info = &lcd_ili9881p_kblk_ad55442_v10_info,
	.ops = &lcd_ili9881p_mipi_operations,
};

